package yi.wuhenbot.Service;

import com.mysql.cj.util.StringUtils;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
import yi.wuhenbot.Controller.BotController;
import yi.wuhenbot.dao.CommandMappingMapper;
import yi.wuhenbot.entity.CommandMapping;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * 内容判断服务（支持动态命令映射执行）
 * 提供统一入口，根据消息类型分发处理
 * **参数顺序固定为：typeID, type, [其他参数...]**
 * @author wuhen
 */
@Service("contentJudgmentService")
public class ContentJudgmentService implements ApplicationContextAware {

    // Spring上下文（用于动态获取Bean实例）
    private ApplicationContext applicationContext;
    private static final Logger logger = LoggerFactory.getLogger(BotController.class);

    @Resource
    private CommandMappingMapper commandMappingMapper;

    @Autowired
    private OrgUserService orgUserService;
    @Autowired
    private KimiUserService kimiUserService;
    @Autowired
    private GroupMessageService groupMessageService;

    /**
     * 内容判断统一入口：匹配命令并执行对应方法
     * **参数顺序固定为：typeID, type, [其他参数...]**
     *
     * @param content 用户输入内容
     * @param userOpenid 用户唯一标识（**注意：此参数在方法内部处理，不直接传递给业务方法**）
     * @param typeID 根据消息类型决定的ID（群ID、用户ID或频道ID）
     * @param type 消息类型字符串（Group/Private/Channel/Direct）
     * @return 方法执行结果
     */
    public String contentJudgment(String content, String userOpenid, String typeID, String type) {


        // 获取用户对话状态（0=未开始对话，1=连续对话中）
        int startCode = orgUserService.getonline_status(typeID,type,userOpenid);

        // 处理AI连续对话模式（startCode=1）
        if (startCode == 1) {
            return handleAIConversation(content, userOpenid, typeID, type);
        } else if (startCode != 0) {
            // 处理未知的对话状态码
            return "未知的对话模式";
        }

        // 验证输入内容是否为空
        if (StringUtils.isNullOrEmpty(content)) {
            return "请输入有效命令！";
        }

        // 从数据库查询匹配的启用命令映射（优先精确匹配，再前缀匹配）
        CommandMapping commandMapping = matchCommandMapping(content);

        // 无匹配命令时，返回复读机效果
        if (commandMapping == null) {
            return "我是复读机呀~您刚说的是：\n" + content;
        }

        try {
            // 解析方法参数类型数组（**typeID和type会自动追加到参数列表末尾**）
            Class<?>[] paramTypes = parseParamTypes(commandMapping.getMethodParamType());

            // 解析方法参数值列表（**参数顺序：typeID, type, [其他参数...]**）
            List<Object> paramValues = parseMethodParams(content, commandMapping, userOpenid, typeID, type);

            // 打印参数日志用于调试
            logger.info("方法参数类型：{}", paramTypes);
            logger.info("方法参数值：{}", paramValues);

            // 动态调用目标方法（**参数顺序严格按 typeID, type, [其他参数...]**）
            Object result = invokeTargetMethod(commandMapping, paramTypes, paramValues, typeID, type);

            // 处理方法返回结果（转为String返回）
            return result != null ? result.toString() : "操作成功！";
        } catch (Exception e) {
            // 异常处理：返回友好提示信息
            e.printStackTrace();
            if (e.getMessage().contains("User not found")) {
                return "用户不存在，请先注册！";
            } else if (e.getMessage().contains("wrong number of arguments")) {
                return "命令参数错误，请检查！";
            }
            return "命令执行失败，请稍后重试！错误原因：" + e.getMessage();
        }
    }

    /**
     * 处理AI连续对话逻辑
     * 根据消息类型调用不同的AI对话服务
     */
    private String handleAIConversation(String content, String userOpenid,String typeID,String type) {
        content=content.trim();
        type = type.trim();
        // 打印全部方法参数
        //System.out.println("typeId: "+typeID+"，type: "+type+"，groupid: "+typeID+"，userOpenid: "+userOpenid+"，content: "+content);
        // 处理退出连续对话命令
        content=content.trim();
        if (content.equals("退出")) {
            orgUserService.updateonline_status(typeID,type,userOpenid, 0);
            kimiUserService.clearKimiUserMessages(typeID,type,userOpenid);
            return "已退出连续对话";
        }

        // 根据消息类型分发AI对话处理
        if ("PRIVATE".equals(type)) {
            return handlePrivateAIChat(typeID,type,userOpenid, content);
        } else if ("GROUP".equals(type) || "CHANNEL".equals(type) || "DIRECT".equals(type)) {
            return handleGroupAIChat(typeID,type,typeID,userOpenid, content);
        }

        return "不支持该消息类型的AI对话";
    }

    /**
     * 处理私聊AI对话
     * 检查并初始化用户对话历史，调用Kimi服务进行对话
     */
    private String handlePrivateAIChat(String typeID,String type,String userOpenid, String content) {
        // 打印参数
        System.out.println("私聊对话消息参数：typeId: "+typeID+"，type: "+type+"，userOpenid: "+userOpenid+"，content: "+content);
        // 检查用户是否存在对话历史，不存在则使用默认模板初始化
        if (!kimiUserService.isKimiUserMessagesExist(userOpenid)) {
            String messages = groupMessageService.selectGroupMessageByGroupid("BF142E0149504B9D91461BDE2E15CED5");
            kimiUserService.updateKimiUserMessages(typeID,type,userOpenid, messages);
        }
        logger.info("开始私聊AI对话，用户：{}", userOpenid);
        return kimiUserService.conversationPrivate(typeID,type,userOpenid, content);
    }

    /**
     * 处理群组AI对话
     * 检查群组是否已存在，获取群组对话历史并调用Kimi服务
     */
    private String handleGroupAIChat(String typeID,String type,String channelId, String userOpenid, String content) {
        // 打印参数
        System.out.println("群组对话消息参数：typeId: "+typeID+"，type: "+type+"，channelId: "+channelId+"，userOpenid: "+userOpenid+"，content: "+content);
        // 检查群组是否已存在，不存在则创建新记录
        if (!groupMessageService.isGroupExist(channelId)) {
            groupMessageService.insertGroupMessage(channelId);
        }

        // 获取群组对话历史
        String groupMessage = groupMessageService.selectGroupMessageByGroupid(channelId);
        logger.info("开始群组AI对话，群组：{}，用户：{}", channelId, userOpenid);
        return kimiUserService.conversationGroup(typeID,type,userOpenid, typeID, groupMessage, content);
    }

    /**
     * 匹配命令映射：优先精确匹配，再前缀匹配
     * 例如："注册"会精确匹配，"改名 张三"会前缀匹配"改名"
     * @param content 用户输入内容
     * @return 匹配的命令映射（null表示无匹配）
     */
    private CommandMapping matchCommandMapping(String content) {
        // 移除首尾空格
        content = content.trim();

        // 判断是否以/开头，删除/前缀（兼容常见命令格式）
        if (content.startsWith("/")) {
            logger.info("原始内容（含/前缀）：{}", content);
            content = content.substring(1);
            logger.info("删除/后的内容：{}", content);
        }

        // 先尝试精确匹配（如"注册"、"签到"）
        CommandMapping exactMatch = commandMappingMapper.getEnableMappingByCommand(content);
        if (exactMatch != null) {
            logger.info("精确匹配成功：{}", exactMatch.getTriggerCommand());
            return exactMatch;
        }

        // 再尝试前缀匹配（如"改名 张三"匹配"改名"）
        String firstWord = content.split(" ")[0];
        logger.info("尝试前缀匹配命令：{}", firstWord);
        CommandMapping prefixMatch = commandMappingMapper.getEnableMappingByCommand(firstWord);
        if (prefixMatch != null) {
            logger.info("前缀匹配成功：{}", prefixMatch.getTriggerCommand());
            return prefixMatch;
        }

        logger.info("未找到匹配的命令");
        return null;
    }

    /**
     * 解析方法参数值列表
     * **参数顺序固定为：typeID, type, [其他参数...]**
     *
     * @param content 用户输入内容
     * @param mapping 命令映射配置
     * @param userOpenid 用户唯一标识
     * @param typeID 消息上下文ID
     * @param type 消息类型
     * @return 参数值列表（**顺序：typeID, type, [其他参数...]**）
     */
    private List<Object> parseMethodParams(String content, CommandMapping mapping,
                                           String userOpenid, String typeID, String type) {
        List<Object> paramValues = new ArrayList<>();
        String methodParamType = mapping.getMethodParamType();

        // **第一步：固定追加typeID和type作为前两个参数**
        paramValues.add(typeID);
        paramValues.add(type);

        // **第二步：处理其他参数（如果有）**
        if (!StringUtils.isNullOrEmpty(methodParamType) && !methodParamType.trim().isEmpty()) {
            // 追加userOpenid作为第三个参数
            paramValues.add(userOpenid);

            // 如果包含逗号，说明有动态参数需要从content中提取
            if (methodParamType.contains(",")) {
                // 删除命令关键字（第一个空格前的内容）
                int firstSpaceIndex = content.indexOf(' ');
                String paramStr = "";
                if (firstSpaceIndex != -1) {
                    paramStr = content.substring(firstSpaceIndex + 1).trim();
                }

                logger.info("提取的参数字符串：{}", paramStr);

                // 按空格分割参数，逐个添加到参数列表（从第四个参数开始）
                if (!StringUtils.isNullOrEmpty(paramStr)) {
                    for (String param : paramStr.split(" ")) {
                        if (!StringUtils.isNullOrEmpty(param)) {
                            paramValues.add(param);
                        }
                    }
                }
            }
        }

        return paramValues;
    }

    /**
     * 解析方法参数类型字符串
     * 将"java.lang.String,java.lang.Integer"转换为Class数组
     * **typeID和type会自动追加到参数类型列表末尾**
     *
     * @param paramTypeStr 数据库存储的参数类型字符串
     * @return 参数类型Class数组
     * @throws ClassNotFoundException 类找不到异常
     */
    private Class<?>[] parseParamTypes(String paramTypeStr) throws ClassNotFoundException {
        List<Class<?>> paramTypeList = new ArrayList<>();

        // **第一步：固定追加typeID和type的类型（String）**
        paramTypeList.add(String.class); // typeID
        paramTypeList.add(String.class); // type

        if (!StringUtils.isNullOrEmpty(paramTypeStr)) {
            // **第二步：追加userOpenid的类型（String）**
            paramTypeList.add(String.class);

            // **第三步：追加其他参数类型**
            String[] paramTypeArr = paramTypeStr.split(",");
            for (int i = 0; i < paramTypeArr.length; i++) {
                String typeName = paramTypeArr[i].trim();
                Class<?> paramType = Class.forName(typeName);

                // userOpenid已经在第二步添加，跳过第一个参数类型
                if (i == 0 && paramType == String.class) {
                    continue;
                }

                paramTypeList.add(paramType);
            }
        }

        return paramTypeList.toArray(new Class[0]);
    }

    /**
     * 动态调用目标方法
     * **参数顺序严格按 typeID, type, [其他参数...]**
     *
     * @param mapping 命令映射配置
     * @param paramTypes 参数类型数组
     * @param paramValues 参数值列表
     * @param typeID 上下文类型ID
     * @param type 上下文消息类型
     * @return 方法执行结果
     * @throws Exception 反射调用异常
     */
    private Object invokeTargetMethod(CommandMapping mapping, Class<?>[] paramTypes,
                                      List<Object> paramValues, String typeID, String type) throws Exception {
        // 从Spring上下文获取目标Bean实例
        String beanName = mapping.getBeanName();
        if (StringUtils.isNullOrEmpty(beanName)) {
            throw new RuntimeException("命令映射中未配置Bean名称：" + beanName);
        }
        Object targetBean = applicationContext.getBean(beanName);

        // 获取目标方法名称
        String methodName = mapping.getMethodName();
        if (StringUtils.isNullOrEmpty(methodName)) {
            throw new RuntimeException("命令映射中未配置方法名称");
        }


        // **查找匹配的方法（支持参数顺序：typeID, type, [其他参数...]）**
        Method targetMethod = findTargetMethod(targetBean.getClass(), methodName, paramTypes);
        logger.info("找到目标方法：{}", targetMethod);

        // **准备最终参数值数组（顺序：typeID, type, [其他参数...]）**
        Object[] finalParamValues = prepareFinalParameters(targetMethod, paramValues);
        logger.info("最终参数值：{}", finalParamValues);

        // 调用方法并返回结果
        return targetMethod.invoke(targetBean, finalParamValues);
    }

    /**
     * 查找匹配的目标方法
     * **支持参数顺序：typeID, type, [其他参数...]**
     */
    private Method findTargetMethod(Class<?> beanClass, String methodName, Class<?>[] paramTypes) throws NoSuchMethodException {
        Method[] methods = beanClass.getMethods();

        for (Method method : methods) {
            if (!method.getName().equals(methodName)) {
                continue;
            }

            Class<?>[] methodParamTypes = method.getParameterTypes();

            // 参数数量必须匹配
            if (methodParamTypes.length != paramTypes.length) {
                continue;
            }

            // 检查参数类型是否完全匹配（typeID和type是String，其他参数按配置）
            boolean match = true;
            for (int i = 0; i < methodParamTypes.length; i++) {
                if (!methodParamTypes[i].equals(paramTypes[i])) {
                    match = false;
                    break;
                }
            }

            if (match) {
                return method;
            }
        }

        throw new NoSuchMethodException("未找到匹配的方法：" + methodName +
                "，期望参数类型：" + java.util.Arrays.toString(paramTypes));
    }

    /**
     * 准备最终参数值数组
     * **参数顺序：typeID, type, [其他参数...]**
     */
    private Object[] prepareFinalParameters(Method method, List<Object> paramValues) {
        return paramValues.toArray();
    }

    /**
     * 实现ApplicationContextAware接口，注入Spring上下文
     * 用于后续动态获取Bean实例
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}